package com.jcompressor.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.apache.commons.lang.StringUtils;
import org.jdom.Document;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.xml.sax.helpers.DefaultHandler;

import com.jcompressor.exceptions.JcompressorException;
import com.jcompressor.preferences.ConfigKeys;

public class JcompressorUtils {
	
	public static Document loadConfiguration(final String config) {
		return loadConfiguration(new File(config));
	}
	
	public static Document loadConfiguration(final File config) {
		try {
			return new SAXBuilder().build(new FileInputStream(config));
		}
		catch (FileNotFoundException e) {
			throw new JcompressorException("Configuration not found: (" + config + ")");
		}
		catch (IOException e) {
			throw new JcompressorException(e);
		}
		catch (JDOMException e) {
			throw new JcompressorException(e);
		}
	}
	
	public static File[] getFileList(final String pattern) {
		try {
			final String baseDir = StringUtils.substringBeforeLast(pattern, ConfigKeys.FILE_SEPARATOR);
			final File dir = new File(baseDir);
			if (dir.exists()) {
				final String filePattern = StringUtils.substringAfterLast(pattern, ConfigKeys.FILE_SEPARATOR);
				if (StringUtils.isBlank(filePattern)) {
					throw new JcompressorException("Filename or pattern is missing (" + pattern + ")");
				}
				
				if (StringUtils.containsNone(filePattern, new char[] {'*'})) {
					final StringBuffer file = new StringBuffer(dir.getPath());
					file.append(ConfigKeys.FILE_SEPARATOR);
					file.append(filePattern);
					
					return new File[] {new File(file.toString())};
				}
				
				final FilenameFilter filter = new WildcardFileFilter(filePattern);
				return dir.listFiles(filter);
			}
			else {
				throw new JcompressorException("Directory not found (" + baseDir + ")");
			}
		}
		catch (Exception e) {
			throw new JcompressorException(e);
		}
	}
	
	public static boolean checkExtensions(final String extension, final String[] files) {
		return JcompressorUtils.test("(" + StringUtils.join(new String[] {ConfigKeys.XML, ConfigKeys.JS, ConfigKeys.CSS}, "|") + ")", extension);
	}
	
	public static boolean test(final String pattern, final String text) {
		final Matcher matcher = Pattern.compile(pattern).matcher(text);
		if (matcher.matches()) {
			return true;
		}
		
		return false;
	}
	
	public static void parse(final InputStream stream, final DefaultHandler handler) throws Exception {
		try {
			SAXParserFactory.newInstance().newSAXParser().parse(stream, handler);
		}
		catch (Exception e) {
			throw new Exception(e);
		}
	}
	
	public static long getTotalFileSize(final List<String> files) {
		long totalSize = 0;
		for (final String file : files) {
			totalSize = (totalSize + new File(file).length());
		}
		
		return totalSize;
	}
	
	public static String percentDiff(final long size1, final long size2) {
		return new DecimalFormat("#0.00 '%'").format(100 - ((new Double(size2) / new Double(size1)) * 100));
	}
	
	public static String formatFileSize(final long size) {
		int divisor = 1;
		String unit = "Bytes";
		if (size >= (1024 * 1024)) {
			divisor = (1024 * 1024);
			unit = "MB";
		}
		else if (size >= 1024) {
			divisor = 1024;
			unit = "KB";
		}
		
		if (divisor == 1) {
			return (size / divisor) + " " + unit;
		}
		
		String afterComma = Long.toString(100 * (size % divisor) / divisor);
		if (afterComma.length() == 1) {
			afterComma = new StringBuffer("0").append(afterComma).toString();
		}
		
		return new StringBuffer(Long.toString(size / divisor)).append('.').append(afterComma).append(' ').append(unit).toString();
	}
	
}